class PAGE_EVENTS {
  constructor() {
    this.IS_SAFARI = typeof safari === "object" && safari.pushNotification;

    const ua = window.navigator.userAgent.toLocaleLowerCase();
    this.IS_IOS = /iphone|ipad|ipod/.test(ua);
    this.IS_Android = /android/.test(ua);

    this.reomveKey = "remove";

    // 页面是否是离开（例如刷新、当前窗口点击外链，关闭浏览器窗口、提交表单请求等）
    this.isLeave = false;
  }

  _isFunction(val) {
    return typeof val === "function";
  }
  _isObject(val) {
    return (
      Object.prototype.toString.call(val).toLowerCase() === "[object object]"
    );
  }
  _firstUpCase(val) {
    return val.slice(0, 1).toUpperCase() + val.slice(1);
  }

  /**
   * 当纯 HTML 被完全加载以及解析时，此时css、js不一定都加载完成
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onReady(callback) {
    const handel = () => {
      this._isFunction(callback) && callback();
    };

    window.addEventListener("DOMContentLoaded", handle);

    const obj = {};
    obj[this.reomveKey] = () =>
      window.removeEventListener("DOMContentLoaded", handel);
    return obj;
  }

  /**
   * 整个页面及所有依赖资源如样式表和图片都已完成加载时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onLoad(callback) {
    const handel = () => {
      this._isFunction(callback) && callback();
    };

    window.addEventListener("load", handel);

    const obj = {};
    obj[this.reomveKey] = () => window.removeEventListener("load", handel);
    return obj;
  }

  /**
   * 离开页面时，例如，刷新、当前窗口点击外链，关闭浏览器窗口、提交表单请求等
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onLeave(callback) {
    const handel = () => {
      this.isLeave = true;
      this._isFunction(callback) && callback();
    };

    window.addEventListener("pagehide", handel);

    const obj = {};
    obj[this.reomveKey] = () => window.removeEventListener("pagehide", handel);
    return obj;
  }

  /**
   * 页面显示时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onShow(callback) {
    const handel = () => {
      if (document.visibilityState === "visible") {
        this._isFunction(callback) && callback();
      }
    };

    document.addEventListener("visibilitychange", handel);

    const obj = {};
    obj[this.reomveKey] = () => {
      document.removeEventListener("visibilitychange", handel);
    };

    return obj;
  }

  /**
   * 页面最小化时、设备锁屏时、切到后台时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onHide(callback) {
    const handel = (event) => {
      // 如果是离开页面，将不再触发隐藏事件
      //if (this.isLeave === true) return;
      if (this.IS_SAFARI && event.persisted) {
        this._isFunction(callback) && callback();
      } else if (document.visibilityState === "hidden") {
        if (this.isLeave === true) return;
        this._isFunction(callback) && callback();
      }
    };

    if (this.IS_SAFARI) window.addEventListener("pagehide", handel);
    else document.addEventListener("visibilitychange", handel);

    const obj = {};
    obj[this.reomveKey] = () =>
      this.IS_SAFARI
        ? window.removeEventListener("pagehide", handel)
        : document.removeEventListener("visibilitychange", handel);
    return obj;
  }

  /**
   * 设备断网时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  offLine(callback) {
    const handel = () => {
      this._isFunction(callback) && callback();
    };

    window.addEventListener("offline", handel);

    const obj = {};
    obj[this.reomveKey] = () => window.removeEventListener("offline", handel);
    return obj;
  }

  /**
   * 设备有网时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onLine(callback) {
    const handel = () => {
      this._isFunction(callback) && callback();
    };

    window.addEventListener("online", handel);

    const obj = {};
    obj[this.reomveKey] = () => window.removeEventListener("online", handel);
    return obj;
  }

  /**
   * 键盘弹出时，页面内输入框获取焦点，键盘弹出时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onKeyboardUp(callback) {
    const handel = () => {
      this._isFunction(callback) && callback();
    };

    document.body.addEventListener("focusin", handel);

    const obj = {};
    obj[this.reomveKey] = () =>
      document.body.removeEventListener("focusin", handel);
    return obj;
  }

  /**
   * 键盘收起时，当点击输入框以外的其他页面区域，或者点击键盘自带的收起时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onKeyboardDown(callback) {
    if (this.IS_IOS) {
      const handel = () => {
        this._isFunction(callback) && callback();
      };

      document.body.addEventListener("focusout", handel);

      const obj = {};
      obj[this.reomveKey] = () =>
        document.body.removeEventListener("focusout", handel);
      return obj;
    } else if (this.IS_Android) {
      const originHeight =
        document.documentElement.clientHeight || document.body.clientHeight;

      const handel = () => {
        const resizeHeight =
          document.documentElement.clientHeight || document.body.clientHeight;
        const activeElement = document.activeElement;
        if (resizeHeight < originHeight) {
          if (
            activeElement &&
            (activeElement.tagName === "INPUT" ||
              activeElement.tagName === "TEXTAREA")
          ) {
            this._isFunction(callback) && callback();
          }
        }
      };

      window.addEventListener("resize", handel);

      const obj = {};
      obj[this.reomveKey] = () => window.removeEventListener("resize", handel);
      return obj;
    }
  }

  /**
   * 设备横屏时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onLandscape(callback) {
    const handel = () => {
      if (window.innerHeight / window.innerWidth < 0.67) {
        this._isFunction(callback) && callback();
      }
    };

    window.addEventListener("resize", handel);

    const obj = {};
    obj[this.reomveKey] = () => {
      window.removeEventListener("resize", handel);
    };

    return obj;
  }

  /**
   * 设备竖屏时
   * @param {*} callback 监听回调函数
   * @returns {remove : 移除监听方法}
   */
  onPortrait(callback) {
    const handel = () => {
      if (window.innerHeight / window.innerWidth > 0.67) {
        this._isFunction(callback) && callback();
      }
    };

    window.addEventListener("resize", handel);

    const obj = {};
    obj[this.reomveKey] = () => {
      window.removeEventListener("resize", handel);
    };

    return obj;
  }

  /**
   * 一次监听多个事件
   * @param { ready, show, hide, leave, line, keyboardUp, keyboardDown, landscape, portrait, offLine  } config
   * @returns {remove : 移除监听方法}
   */
  on(config) {
    if (!this._isObject(config)) return;

    this._catchRemoveListenFunctions = [];
    for (let key in config) {
      const _key = ["offLine"].includes(key)
        ? key
        : "on" + this._firstUpCase(key);
    //   alert(_key);
      if (this._isFunction(this[_key]) && this._isFunction(config[key])) {
        const result = this[_key](config[key]);
        this._catchRemoveListenFunctions.push(result[this.reomveKey]);
      }
    }

    const obj = {};
    obj[this.reomveKey] = () => {
      this._catchRemoveListenFunctions.forEach((handel) => handel());
      this._catchRemoveListenFunctions = [];
    };
    return obj;
  }
}

export default new PAGE_EVENTS();
